<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src=""></script>
</head>
<style>
    .slider-bar {
        position: absolute;
        left: 50%;
        top: 300px;
        margin-left: 600px;
        width: 45px;
        height: 130px;
        background-color: pink;
    }

    .w {
        width: 1200px;
        margin: 10px auto;
    }

    .header {
        height: 150px;
        background-color: purple;
    }

    .banner {
        height: 250px;
        background-color: skyblue;
    }

    .main {
        height: 1000px;
        background-color: yellowgreen;
    }

    span {
        display: none;
        position: absolute;
        bottom: 0;
    }
</style>
<body>

<div class="slider-bar">
    <span class="goBack">返回顶部</span>
</div>
<div class="header w">头部区域</div>
<div class="banner w">banner区域</div>
<div class="main w">主体部分</div>

<script>

    // 1.获取元素
    var sliderBar = document.querySelector('.slider-bar');
    var banner = document.querySelector('.banner');
    var main = document.querySelector('.main');
    var goBack = document.querySelector('.goBack');


    // banner.offsetTop 就是被卷去头部的大小
    // console.log(banner.offsetTop)
    /**
     * 为什么这里一定要写在滚动的外面?
     * 不能将这个 banner.offsetTop写入到里面
     * #
     * 原因: 写在外面是因为, bannerTop和sliderBarTop 是一个固定的值
     * 写在 scroll里面的话, 随着页面发生滚动事件, 这两个值会一直发生变化!!!
     *
     */
    var bannerTop = banner.offsetTop;
    var sliderBarTop = sliderBar.offsetTop;
    var mainTop = main.offsetTop;
    var goBackTop = goBack.offsetTop;

    // 2.页面滚动事件 scroll
    document.addEventListener('scroll', function () {
        // 页面被卷去的头部: 可以通过window.pageYOffset 获得, 如果是被卷去的左侧 -> window.pageXOffset
        console.log(window.pageYOffset)

        // 3.当我们页面被卷去的头部大于等于了 bannerTop, 此时侧边栏就要更改固定定位
        if (window.pageYOffset >= bannerTop) {
            sliderBar.style.position = 'fixed';
            sliderBar.style.top = sliderBarTop - bannerTop + 'px';
        } else {
            sliderBar.style.position = 'absolute';
            sliderBar.style.top = sliderBarTop + 'px';
        }

        // 4.当我们页面滚动到 main 盒子, 就显示 goBack模块
        if (window.pageYOffset >= mainTop) {
            goBack.style.display = 'block';
        } else {
            goBack.style.display = 'none';
        }
    })

    // 3.当我们点击了返回顶部模块, 就让窗口滚动的页面的最上方
    goBack.addEventListener('click', function () {
        // 滚动窗口至文档中的特定位置, 里面的x和y是不跟单位的, 直接写数值
        // window.scroll(0, 0)
        // 因为是窗口滚动, 所以对象时window
        animate(window, 0)
    })

    /**
     * js实现动画
     * @param obj
     * @param target
     * @param callback
     */
    function animate(obj, target, callback) {
        // console.log(callback);  callback = function() {}  调用的时候 callback()

        // 先清除以前的定时器，只保留当前的一个定时器执行
        clearInterval(obj.timer);
        obj.timer = setInterval(function () {
            // 步长值写到定时器的里面
            // 把我们步长值改为整数 不要出现小数的问题
            // var step = Math.ceil((target - obj.offsetLeft) / 10);
            let step = (target - window.pageYOffset) / 10;
            step = step > 0 ? Math.ceil(step) : Math.floor(step);
            if (window.pageYOffset === target) {
                // 停止动画 本质是停止定时器
                clearInterval(obj.timer);
                // 回调函数写到定时器结束里面
                // if (callback) {
                //     // 调用函数
                //     callback();
                // }
                callback && callback();
            }
            // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式：(目标值 - 现在的位置) / 10
            // obj.style.left = window.pageYOffset + step + 'px';
            window.scroll(0, window.pageYOffset + step)
        }, 15);
    }


</script>
</body>
</html>
